#include "ulib.h"
#include "syscall.h"

#define RKV_HASH 197
#define RKV_SIZE 10240

static int      rkv_h[RKV_HASH];
static uint32_t rkv_count;
static uint32_t rkv_k[RKV_SIZE];
static uint32_t rkv_v_size[RKV_SIZE];
static void    *rkv_v_ptr[RKV_SIZE];
static int      rkv_n[RKV_SIZE];

extern char rkv_data[];

static inline uint32_t
rkv_hash(uint32_t k)
{
	 return k % RKV_HASH;
}

static int
rkv_find(uint32_t k, int touch)
{
	 int hash = rkv_hash(k);
	 int cur = rkv_h[hash];
	 while (cur != -1)
	 {
		  if (rkv_k[cur] == k)
			   return cur;
		  else cur = rkv_n[cur];
	 }
	 if (touch && rkv_count < RKV_SIZE)
	 {
		  cur = rkv_count ++;
		  
		  rkv_k[cur] = k;
		  rkv_n[cur] = rkv_h[hash];
		  rkv_h[hash] = cur;
	 }
	 return cur;
}

int
rkv_init(void)
{
	 int i;
	 for (i = 0; i != RKV_SIZE; ++ i)
	 {
		  rkv_h[i] = -1;
	 }
	 rkv_count = 0;

	 char *cur = rkv_data;
	 while (1)
	 {
		  char end_flags = *(cur ++);
		  if (end_flags) break;

		  uint32_t key = *(uint32_t *)cur;
		  cur += sizeof(key);
		  
		  uint32_t size = *(uint32_t *)cur;
		  cur += sizeof(size);

		  int idx;
		  if ((idx = rkv_find(key, 1)) != -1)
		  {
			   rkv_v_size[idx] = size;
			   rkv_v_ptr[idx]  = cur;
		  }

		  cur += size;
	 }

	 sc_kprintf("rkvfs: %d record(s) read\n", rkv_count);

	 return 0;
}

int
rkv_get(uint32_t k, const char **data_ptr, uint32_t *size_ptr)
{
	 int idx = rkv_find(k, 0);
	 if (idx == -1) return -1;

	 *data_ptr = rkv_v_ptr[idx];
	 *size_ptr = rkv_v_size[idx];

	 return 0;
}
